package com.ruoyi.aitqjkj.service;

import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.aitcommon.anotation.ServiceLog;
import com.ruoyi.aitcommon.service.IAitEntityInfoService;
import com.ruoyi.aitcommon.utils.EntityCache;
import com.ruoyi.aitcommon.utils.ExceptionUtils;
import com.ruoyi.aitcommon.utils.JSONResult;
import com.ruoyi.aitcommon.utils.RestServiceUtils;
import com.ruoyi.aitcommon.vo.AggMap;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.security.MessageDigest;

@Service
public class QJKJWMSRestService {
    @Autowired
    IAitEntityInfoService infoService;
    @Autowired
    EntityCache entityCache;

    /**
     * 生成签名（修正逻辑）
     * 根据您提供的预执行操作，签名生成流程为：
     * 1. appSecret + requestJson + appSecret
     * 2. MD5加密
     * 3. Base64编码
     * 4. 转为大写
     */
    private String getSign(String requestJson,String appSecret) throws Exception {
        String signData = appSecret + (requestJson != null ? requestJson : "") + appSecret;
        // MD5加密
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(signData.getBytes(StandardCharsets.UTF_8));
        byte[] md5Bytes = md.digest();

        // 将MD5结果转为16进制字符串（小写）
        StringBuilder hexString = new StringBuilder();
        for (byte b : md5Bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        String md5Result = hexString.toString();

        // Base64编码并转为大写
        String base64Result = Base64.getEncoder().encodeToString(md5Result.getBytes(StandardCharsets.UTF_8));
        return base64Result.toUpperCase();
    }

    private void checkRetJson(JSONObject retJson) throws Exception {
        ExceptionUtils.checkBlankOrUndefined(retJson, "retJson为空");
        final JSONObject response = retJson.getJSONObject("Response");
        ExceptionUtils.checkBlankOrUndefined(response, "response为空");
        final JSONObject aReturn = response.getJSONObject("return");
        ExceptionUtils.checkBlankOrUndefined(aReturn, "aReturn为空");
        final String returnFlag = aReturn.getString("returnFlag");
        if(returnFlag.equals("0")){
            //失败
            ExceptionUtils.throwException(null, "调用失败,{}", aReturn.getString("returnDesc"));
        }else if(returnFlag.equals("1")){
            //成功
        }else if (returnFlag.equals("2")){
            //部分成功
            ExceptionUtils.throwException(null, "调用部分成功,{}", aReturn.getString("returnDesc"));
        }
    }

    /**
     * 调用rest接口
     * 使用SDK调用
     * @param url
     * @param param,包含:method,apptoken,appSecret,lineField
     * @param data
     * @return
     */
    private JSONObject restInvoke(String url, Map<String, Object> param, Map<String, Object> data) throws Exception {
        // 生成签名（修正后的逻辑）
        String appSecret=param.get("appSecret").toString();
        String bodyJson = this.getJSONBody(data,param).toString();
        String sign = getSign(bodyJson,appSecret);
        // 构造参数
        String method=param.get("method").toString();
        String apptoken=param.get("apptoken").toString();
        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timestamp=sdf.format(new java.util.Date());
        Map<String,Object> query=new HashMap<>();
        query.put("method", method);
        query.put("apptoken", apptoken);
        query.put("timestamp", timestamp);
        query.put("sign", URLEncoder.encode(sign.toUpperCase(), "utf-8"));
        query.put("format", "json");
        // 远程调用
        final String retStr = RestServiceUtils.post(url,query, null, bodyJson);
        // 获取返回值
        JSONObject retJson = JSONObject.parseObject(retStr);
        checkRetJson(retJson);
        return retJson;
    }

    /**
     * 构造JSON BODY数据
     *
     * @param data
     * @return
     */
    private JSONObject getJSONBody(Map<String, Object> data,Map<String, Object> param) throws Exception {
        String lineField = param.get("lineField").toString();
        AggMap aggMap = new AggMap(data);
        JSONObject header=new JSONObject(aggMap.toMap(null, lineField));
        JSONArray headers=new JSONArray();
        headers.add(header);
        JSONObject headerJson = new JSONObject();
        headerJson.put("header",headers);
        JSONObject dataJson = new JSONObject();
        dataJson.put("data",headerJson);
        return dataJson;
    }

    /**
     * 保存服务
     * @param datas 数据列表,要求主子表结构
     * @param param 参数
     * @param url
     * @param entityInfo
     * @return
     */
    @ServiceLog("保存服务")
    public List<JSONObject> entitySave(List<Map<String, Object>> datas, Map<String, Object> param, String url, JSONObject entityInfo) throws Exception {
        List<JSONObject> retlist = new ArrayList();
        ExceptionUtils.checkBlankOrUndefined(param, "param");
        ExceptionUtils.checkBlankOrUndefined(url, "url为空");
        ExceptionUtils.checkBlankOrUndefined(entityInfo, "entityInfo为空");

        List<Map<String, Object>> filterList = this.entityCache.filterEntityChange(entityInfo, datas);
        // 如果datas或者u9cOrderNo为空就continue;
        for (Map<String, Object> data : filterList) {
            try {
                JSONObject retjson = this.restInvoke(url, param, data);
                this.infoService.insertAitEntityInfo(entityInfo, data, (Exception) null);
                retlist.add(retjson);
            } catch (Exception ex) {
                this.infoService.insertAitEntityInfo(entityInfo, data, ex);
                retlist.add(JSONResult.error(ex.getMessage()));
            }
        }


        return retlist;
    }

}
